package org.jetlinks.pro.things.impl;

import org.hswebframework.web.exception.I18nSupportException;
import org.jetlinks.core.things.ThingRpcSupport;
import org.jetlinks.pro.things.*;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import reactor.core.publisher.Mono;

import javax.annotation.Nonnull;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultThingsManagerContext implements ThingsManagerContext, BeanPostProcessor {

    private final Map<String, ThingsConnectorProvider> providers = new ConcurrentHashMap<>();
    private final Map<String, ThingsRpcSupportProvider> supportProviders = new ConcurrentHashMap<>();
    private final Map<String, ThingMessageConverterProvider> converterProviders = new ConcurrentHashMap<>();

    @Nonnull
    @Override
    public Mono<ThingsConnector> createConnector(@Nonnull String provider,
                                                 @Nonnull Map<String, Object> configuration) {
        return Mono
            .justOrEmpty(providers.get(provider))
            .switchIfEmpty(Mono.error(() -> new I18nSupportException("error.unsupported_thing_connector_provider", provider)))
            .flatMap(_provider -> _provider.createConnector(configuration));
    }

    @Nonnull
    @Override
    public Mono<ThingRpcSupport> createRpcSupport(@Nonnull String provider, @Nonnull Map<String, Object> configuration) {
        return Mono
            .justOrEmpty(supportProviders.get(provider))
            .switchIfEmpty(Mono.error(() -> new I18nSupportException("error.unsupported_thing_rpc_provider", provider)))
            .flatMap(_provider -> _provider.createSupport(configuration));
    }

    @Nonnull
    @Override
    public Mono<ThingMessageConverter> createConverter(@Nonnull String provider, @Nonnull Map<String, Object> configuration) {
        return Mono
            .justOrEmpty(converterProviders.get(provider))
            .switchIfEmpty(Mono.error(() -> new I18nSupportException("error.unsupported_thing_converter_provider", provider)))
            .flatMap(_provider -> _provider.createConverter(configuration));
    }

    private void register(ThingsConnectorProvider provider) {
        providers.put(provider.getId(), provider);

    }

    private void register(ThingsRpcSupportProvider provider) {
        supportProviders.put(provider.getId(), provider);
    }

    private void register(ThingMessageConverterProvider provider) {
        converterProviders.put(provider.getId(), provider);
    }

    @Override
    public Object postProcessAfterInitialization(@Nonnull Object bean,
                                                 @Nonnull String beanName) throws BeansException {
        if (bean instanceof ThingsConnectorProvider) {
            register(((ThingsConnectorProvider) bean));
        }
        if (bean instanceof ThingsRpcSupportProvider) {
            register(((ThingsRpcSupportProvider) bean));
        }
        if (bean instanceof ThingMessageConverterProvider) {
            register(((ThingMessageConverterProvider) bean));
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
